package com.google.code.sip.ucenter.web.admin.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.mvel2.MVEL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;

import com.google.code.sip.ucenter.model.CreditType;
import com.google.code.sip.ucenter.model.Setting;
import com.google.code.sip.ucenter.service.CreditTypeManager;
import com.google.code.sip.ucenter.service.SettingManager;
import com.google.code.sip.ucenter.web.BaseController;

@Controller
public class SettingController extends BaseController {

	@Autowired
	private SettingManager settingManager;
	@Autowired
	private CreditTypeManager creditTypeManager;

	@RequestMapping("/admin/setting.do")
	public ModelAndView settings() {
		ModelAndView mv = new ModelAndView("admin.setting.settings");
		mv.addAllObjects(referenceData());
		return mv;
	}

	@RequestMapping("/admin/setting!input.do")
	public ModelAndView input() {
		return new ModelAndView("admin.setting.input");
	}

	@RequestMapping("/admin/setting!save.do")
	public ModelAndView save(HttpServletRequest request,
			@ModelAttribute("setting") Setting setting) {
		if (checkSetting(setting)) {
			String name = setting.getName();
			if (Setting.CREDIT_FORMULA.equals(name)) {
				if (checkCreditFormula(setting.getValue())) {
					settingManager.saveSetting(setting);
				} else {
					this.saveError(request, "总积分计算公式非法！");
				}
			} else {
				if (setting != null) {
					settingManager.saveSetting(setting);
				}
			}
			return settings();
		} else {
			this.saveError(request, "参数名称、参数值、参数标题不能为空！");
			return input();
		}
	}

	@RequestMapping("/admin/setting!saveAll.do")
	public ModelAndView saveAll(HttpServletRequest request) {
		// 从request中获取含属性前缀名的参数,构造去除前缀名后的参数Map.
		Map<String, Object> paramMap = WebUtils.getParametersStartingWith(
				request, "setting_");
		for (Map.Entry<String, Object> entity : paramMap.entrySet()) {
			String name = entity.getKey();
			String value = (String) entity.getValue();
			if (Setting.CREDIT_FORMULA.equals(name)) {
				if (checkCreditFormula(value)) {
					Setting setting = settingManager.getSettingByName(name);
					setting.setValue(value);
					settingManager.saveSetting(setting);
				} else {
					this.saveError(request, "总积分计算公式非法！");
				}
			} else {
				Setting setting = settingManager.getSettingByName(name);
				if (setting != null) {
					setting.setValue(value);
					settingManager.saveSetting(setting);
				}
			}
		}
		return settings();
	}

	@RequestMapping("/admin/setting!delete.do")
	public ModelAndView delete(@RequestParam("id") String id) {
		if (StringUtils.isNotEmpty(id)) {
			settingManager.deleteSetting(id);
		}
		return settings();
	}

	private boolean checkSetting(Setting setting) {
		if (StringUtils.isBlank(setting.getName())) {
			return false;
		}
		if (StringUtils.isBlank(setting.getValue())) {
			return false;
		}
		if (StringUtils.isBlank(setting.getDisplayName())) {
			return false;
		}
		return true;
	}

	/**
	 * 检查积分公式是否合法
	 * 
	 * @param formula
	 *            积分公式
	 * @return
	 */
	private boolean checkCreditFormula(String formula) {
		String formula2 = formula;
		if (StringUtils.isBlank(formula)) {
			return true;
		}
		List<String> creditTypeNames = creditTypeManager
				.getAllCreditTypeNames();
		if (creditTypeNames == null || creditTypeNames.isEmpty()) {
			return false;
		}
		// 去除空格，括号
		formula = StringUtils.replace(formula, " ", "");
		formula = StringUtils.replace(formula, "(", "");
		formula = StringUtils.replace(formula, ")", "");
		String[] fomulaElements = formula.split("\\+|-");
		for (String fomulaElement : fomulaElements) {
			String[] elements = fomulaElement.split("\\*|/");
			for (String element : elements) {
				if (!NumberUtils.isNumber(element)
						&& !creditTypeNames.contains(element)) {
					return false;
				}
			}
		}
		List<CreditType> creditTypes = creditTypeManager.getAllCreditTypes();
		Map<String, Object> vars = new HashMap<String, Object>(creditTypes
				.size());
		for (CreditType creditType : creditTypes) {
			vars.put(creditType.getName(), 1);
		}
		try {
			MVEL.eval(formula2, vars, Integer.class);
			return true;
		} catch (RuntimeException e) {
			return false;
		}
	}

	protected Map<String, Object> referenceData() {
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("settings", settingManager.getAllSettings());
		dataMap.put("creditTypes", creditTypeManager.getAllCreditTypes());
		return dataMap;
	}

}
